<template>
  <view class="uni-calendar">
    <view v-if="!insert&&show" class="uni-calendar__mask" :class="{'uni-calendar--mask-show':aniMaskShow}"
      @click="clean"></view>
    <view v-if="insert || show" class="uni-calendar__content"
      :class="{'uni-calendar--fixed':!insert,'uni-calendar--ani-show':aniMaskShow}">
      <view v-if="!insert" class="uni-calendar__header uni-calendar--fixed-top">
        <view class="uni-calendar__header-btn-box" @click="close">
          <text class="uni-calendar__header-text uni-calendar--fixed-width">{{cancelText}}</text>
        </view>
        <view class="uni-calendar__header-btn-box" @click="confirm">
          <text class="uni-calendar__header-text uni-calendar--fixed-width">{{okText}}</text>
        </view>
      </view>
      <view class="uni-calendar__header">
        <view class="uni-calendar__header-btn-box" @click.stop="pre">
          <view class="uni-calendar__header-btn uni-calendar--left"></view>
        </view>
        <picker mode="date" :value="date" fields="month" @change="bindDateChange">
          <text class="uni-calendar__header-text">{{ (nowDate.year || '') + '年' + ( nowDate.month || '') + '月'}}</text>
        </picker>
        <view class="uni-calendar__header-btn-box" @click.stop="next">
          <view class="uni-calendar__header-btn uni-calendar--right"></view>
        </view>
        <text v-if="showToday" class="uni-calendar__backtoday" @click="backtoday">{{todayText}}</text>
      </view>

      <slot name="default"></slot>

      <view class="uni-calendar__box">
        <view v-if="showMonth" class="uni-calendar__box-bg">
          <text class="uni-calendar__box-bg-text">{{nowDate.month}}</text>
        </view>
        <view class="uni-calendar__weeks">
          <view class="uni-calendar__weeks-day">
            <text class="uni-calendar__weeks-day-text">{{SUNText}}</text>
          </view>
          <view class="uni-calendar__weeks-day">
            <text class="uni-calendar__weeks-day-text">{{monText}}</text>
          </view>
          <view class="uni-calendar__weeks-day">
            <text class="uni-calendar__weeks-day-text">{{TUEText}}</text>
          </view>
          <view class="uni-calendar__weeks-day">
            <text class="uni-calendar__weeks-day-text">{{WEDText}}</text>
          </view>
          <view class="uni-calendar__weeks-day">
            <text class="uni-calendar__weeks-day-text">{{THUText}}</text>
          </view>
          <view class="uni-calendar__weeks-day">
            <text class="uni-calendar__weeks-day-text">{{FRIText}}</text>
          </view>
          <view class="uni-calendar__weeks-day">
            <text class="uni-calendar__weeks-day-text">{{SATText}}</text>
          </view>
        </view>
        <view class="uni-calendar__weeks" v-for="(item,weekIndex) in weeks" :key="weekIndex">
          <view class="uni-calendar__weeks-item" v-for="(weeks,weeksIndex) in item" :key="weeksIndex">
            <calendar-item class="uni-calendar-item--hook" :weeks="weeks" :calendar="calendar" :selected="selected"
              :lunar="lunar" @change="choiceDate"></calendar-item>
          </view>
        </view>
      </view>
    </view>
  </view>
</template>

<script>
  import Calendar from './util.js';
  import calendarItem from './sl-uni-calendar-item.vue'
  import {
    initVueI18n
  } from '@dcloudio/uni-i18n'
  import messages from './i18n/index.js'
  const { t } = initVueI18n(messages)
  /**
   * Calendar 日历
   * @description 日历组件可以查看日期，选择任意范围内的日期，打点操作。常用场景如：酒店日期预订、火车机票选择购买日期、上下班打卡等
   * @tutorial https://ext.dcloud.net.cn/plugin?id=56
   * @property {String} date 自定义当前时间，默认为今天
   * @property {Boolean} lunar 显示农历
   * @property {String} startDate 日期选择范围-开始日期
   * @property {String} endDate 日期选择范围-结束日期
   * @property {Boolean} range 范围选择
   * @property {Boolean} insert = [true|false] 插入模式,默认为false
   * 	@value true 弹窗模式
   * 	@value false 插入模式
   * @property {Boolean} clearDate = [true|false] 弹窗模式是否清空上次选择内容
   * @property {Array} selected 打点，期待格式[{date: '2019-06-27', info: '签到', data: { custom: '自定义信息', name: '自定义消息头',xxx:xxx... }}]
   * @property {Boolean} showMonth 是否选择月份为背景
   * @event {Function} change 日期改变，`insert :ture` 时生效
   * @event {Function} confirm 确认选择`insert :false` 时生效
   * @event {Function} monthSwitch 切换月份时触发
   * @example <uni-calendar :insert="true":lunar="true" :start-date="'2019-3-2'":end-date="'2019-5-20'"@change="change" />
   */
  export default {
    components: {
      calendarItem
    },
    emits: ['close', 'confirm', 'change', 'monthSwitch'],
    props: {
      date: {
        type: String,
        default: ''
      },
      selected: {
        type: Array,
        default () {
          return []
        }
      },
      lunar: {
        type: Boolean,
        default: false
      },
      startDate: {
        type: String,
        default: ''
      },
      endDate: {
        type: String,
        default: ''
      },
      range: {
        type: Boolean,
        default: false
      },
      insert: {
        type: Boolean,
        default: true
      },
      showMonth: {
        type: Boolean,
        default: true
      },
      showToday: {
        type: Boolean,
        default: false
      },
      clearDate: {
        type: Boolean,
        default: true
      }
    },
    data() {
      return {
        show: false,
        weeks: [],
        calendar: {},
        nowDate: '',
        aniMaskShow: false
      }
    },
    computed: {
      /**
       * for i18n
       */

      okText() {
        return t("uni-calender.ok")
      },
      cancelText() {
        return t("uni-calender.cancel")
      },
      todayText() {
        return t("uni-calender.today")
      },
      monText() {
        return t("uni-calender.MON")
      },
      TUEText() {
        return t("uni-calender.TUE")
      },
      WEDText() {
        return t("uni-calender.WED")
      },
      THUText() {
        return t("uni-calender.THU")
      },
      FRIText() {
        return t("uni-calender.FRI")
      },
      SATText() {
        return t("uni-calender.SAT")
      },
      SUNText() {
        return t("uni-calender.SUN")
      },
    },
    watch: {
      date(newVal) {
        // this.cale.setDate(newVal)
        this.init(newVal)
      },
      startDate(val) {
        this.cale.resetSatrtDate(val)
        this.cale.setDate(this.nowDate.fullDate)
        this.weeks = this.cale.weeks
      },
      endDate(val) {
        this.cale.resetEndDate(val)
        this.cale.setDate(this.nowDate.fullDate)
        this.weeks = this.cale.weeks
      },
      selected(newVal) {
        this.cale.setSelectInfo(this.nowDate.fullDate, newVal)
        this.weeks = this.cale.weeks
      }
    },
    created() {
      // 获取日历方法实例
      this.cale = new Calendar({
        // date: new Date(),
        selected: this.selected,
        startDate: this.startDate,
        endDate: this.endDate,
        range: this.range,
      })
      // 选中某一天
      // this.cale.setDate(this.date)
      this.init(this.date)
      // this.setDay
    },
    methods: {
      // 取消穿透
      clean() {},
      bindDateChange(e) {
        const value = e.detail.value + '-1'
        console.log(this.cale.getDate(value));
        this.setDate(value)
      },
      /**
       * 初始化日期显示
       * @param {Object} date
       */
      init(date) {
        this.cale.setDate(date)
        this.weeks = this.cale.weeks
        this.nowDate = this.calendar = this.cale.getInfo(date)
      },
      /**
       * 打开日历弹窗
       */
      open() {
        // 弹窗模式并且清理数据
        if (this.clearDate && !this.insert) {
          this.cale.cleanMultipleStatus()
          // this.cale.setDate(this.date)
          this.init(this.date)
        }
        this.show = true
        this.$nextTick(() => {
          setTimeout(() => {
            this.aniMaskShow = true
          }, 50)
        })
      },
      /**
       * 关闭日历弹窗
       */
      close() {
        this.aniMaskShow = false
        this.$nextTick(() => {
          setTimeout(() => {
            this.show = false
            this.$emit('close')
          }, 300)
        })
      },
      /**
       * 确认按钮
       */
      confirm() {
        this.setEmit('confirm')
        this.close()
      },
      /**
       * 变化触发
       */
      change() {
        if (!this.insert) return
        this.setEmit('change')
      },
      /**
       * 选择月份触发
       */
      monthSwitch() {
        let {
          year,
          month
        } = this.nowDate
        this.$emit('monthSwitch', {
          year,
          month: Number(month)
        })
      },
      /**
       * 派发事件
       * @param {Object} name
       */
      setEmit(name) {
        let {
          year,
          month,
          date,
          fullDate,
          lunar,
          extraInfo
        } = this.calendar
        this.$emit(name, {
          range: this.cale.multipleStatus,
          year,
          month,
          date,
          fulldate: fullDate,
          lunar,
          extraInfo: extraInfo || {}
        })
      },
      /**
       * 选择天触发
       * @param {Object} weeks
       */
      choiceDate(weeks) {
        if (weeks.disable) return
        this.calendar = weeks
        // 设置多选
        this.cale.setMultiple(this.calendar.fullDate)
        this.weeks = this.cale.weeks
        this.change()
      },
      /**
       * 回到今天
       */
      backtoday() {
        console.log(this.cale.getDate(new Date()).fullDate);
        let date = this.cale.getDate(new Date()).fullDate
        // this.cale.setDate(date)
        this.init(date)
        this.change()
      },
      /**
       * 上个月
       */
      pre() {
        const preDate = this.cale.getDate(this.nowDate.fullDate, -1, 'month').fullDate
        this.setDate(preDate)
        this.monthSwitch()

      },
      /**
       * 下个月
       */
      next() {
        const nextDate = this.cale.getDate(this.nowDate.fullDate, +1, 'month').fullDate
        this.setDate(nextDate)
        this.monthSwitch()
      },
      /**
       * 设置日期
       * @param {Object} date
       */
      setDate(date) {
        this.cale.setDate(date)
        this.weeks = this.cale.weeks
        this.nowDate = this.cale.getInfo(date)
      }
    }
  }
</script>

<style lang="scss" scoped>
  $uni-bg-color-mask: rgba($color: #000000, $alpha: 0.4);
  $uni-border-color: #EDEDED;
  $uni-text-color: #333;
  $uni-bg-color-hover:#f1f1f1;
  $uni-font-size-base:14px;
  $uni-text-color-placeholder: #808080;
  $uni-color-subtitle: #555555;
  $uni-text-color-grey:#999;

  .uni-calendar {
    /* #ifndef APP-NVUE */
    display: flex;
    /* #endif */
    flex-direction: column;
  }

  .uni-calendar__mask {
    position: fixed;
    bottom: 0;
    top: 0;
    left: 0;
    right: 0;
    background-color: $uni-bg-color-mask;
    transition-property: opacity;
    transition-duration: 0.3s;
    opacity: 0;
    /* #ifndef APP-NVUE */
    z-index: 99;
    /* #endif */
  }

  .uni-calendar--mask-show {
    opacity: 1
  }

  .uni-calendar--fixed {
    position: fixed;
    /* #ifdef APP-NVUE */
    bottom: 0;
    /* #endif */
    left: 0;
    right: 0;
    transition-property: transform;
    transition-duration: 0.3s;
    transform: translateY(460px);
    /* #ifndef APP-NVUE */
    bottom: calc(var(--window-bottom));
    z-index: 99;
    /* #endif */
  }

  .uni-calendar--ani-show {
    transform: translateY(0);
  }

  .uni-calendar__content {
    // background-color: #fff;
  }

  .uni-calendar__header {
    position: relative;
    /* #ifndef APP-NVUE */
    display: flex;
    /* #endif */
    flex-direction: row;
    justify-content: center;
    align-items: center;
    height: 50px;
    margin-top: 40upx;
    // border-bottom-color: $uni-border-color;
    // border-bottom-style: solid;
    // border-bottom-width: 1px;
  }

  .uni-calendar--fixed-top {
    /* #ifndef APP-NVUE */
    display: flex;
    /* #endif */
    flex-direction: row;
    justify-content: space-between;
    border-top-color: $uni-border-color;
    border-top-style: solid;
    border-top-width: 1px;
  }

  .uni-calendar--fixed-width {
    width: 50px;
    // padding: 0 15px;
  }

  .uni-calendar__backtoday {
    position: absolute;
    right: 0;
    top: 25rpx;
    padding: 0 5px;
    padding-left: 10px;
    height: 25px;
    line-height: 25px;
    font-size: 12px;
    border-top-left-radius: 25px;
    border-bottom-left-radius: 25px;
    color: $uni-text-color;
    background-color: $uni-bg-color-hover;
  }

  .uni-calendar__header-text {
    text-align: center;
    width: 100px;
    // font-size: $uni-font-size-base;
    // color: $uni-text-color;
    font-size: 36upx;
    color: #2A2929;
  }

  .uni-calendar__header-btn-box {
    /* #ifndef APP-NVUE */
    display: flex;
    /* #endif */
    flex-direction: row;
    align-items: center;
    justify-content: center;
    width: 80upx;
    height: 50px;
  }

  .uni-calendar__header-btn {
    width: 0;
    height: 0;
    border-width: 12upx;
    border-style: solid;
    border-color: transparent transparent transparent #818181;
    // transform: rotate(0);
  }

  .uni-calendar--left {
    transform: rotate(-180deg);
  }

  .uni-calendar--right {
    // transform: rotate(135deg);
  }

  .uni-calendar__weeks {
    position: relative;
    /* #ifndef APP-NVUE */
    display: flex;
    /* #endif */
    flex-direction: row;
  }

  .uni-calendar__weeks-item {
    flex: 1;
  }

  .uni-calendar__weeks-day {
    flex: 1;
    /* #ifndef APP-NVUE */
    display: flex;
    /* #endif */
    flex-direction: column;
    justify-content: center;
    align-items: center;
    height: 45px;
    border-bottom-color: #F5F5F5;
    border-bottom-style: solid;
    border-bottom-width: 1px;
  }

  .uni-calendar__weeks-day-text {
    font-size: 24upx;
    color: #818181;
  }

  .uni-calendar__box {
    position: relative;
    background-color: #fff;
  }

  .uni-calendar__box-bg {
    /* #ifndef APP-NVUE */
    display: flex;
    /* #endif */
    justify-content: center;
    align-items: center;
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
  }

  .uni-calendar__box-bg-text {
    font-size: 200px;
    font-weight: bold;
    color: $uni-text-color-grey;
    opacity: 0.1;
    text-align: center;
    /* #ifndef APP-NVUE */
    line-height: 1;
    /* #endif */
  }
</style>
